﻿using System;
using System.IO;
using HK.Core.Common;
using HK.Core.Common.Data;
using HK.Core.Serializable;
using UnityEngine;
using HLogger = HK.Core.Logs.Logger;

namespace HK.Core.Utils
{
    /// <summary>
    /// 工具类 : 可序列化资产类
    /// </summary>
    public static class UtilsSAssets
    {

        /// <summary>
        /// asset文件数据路径.
        /// </summary>
        private static readonly string AssetDataDir = Const.HK_RESOURCE_ASSETS;
        
        /// <summary>
        /// 取得Asset文件目录路径.
        /// </summary>
        /// <param name="iDir">Asset存放目录文件（不指定：当前选定对象所在目录）.</param>
        /// <param name="iExistVerify">存在校验（会自动生成相应目录）.</param>
        /// <param name="iFullPath">返回是否返回全路径.</param>
        /// <returns>取得Asset文件目录路径.</returns>
        public static string GetAssetFileDir (string iDir = null, bool iExistVerify = false, bool iFullPath = false) 
        {
            var dirTmp = iDir;
			
            if (!string.IsNullOrEmpty(dirTmp))
            {
                // 目录校验
                var flg = true;
                if (iExistVerify && !Directory.Exists(dirTmp))
                {
                    flg = UtilsIo.CheckAndCreateDirByFullDir(dirTmp);
                }
                return flg ? dirTmp : null;
            }
			
            dirTmp = AssetDataDir;
            var fullDir = dirTmp;
            if (!iFullPath)
            {
                dirTmp = UtilsIo.ConvertToAssetPath(dirTmp);
                if (string.IsNullOrEmpty(dirTmp))
                {
                    HLogger.Error($"UtilsAsset::GetAssetFileDir():UtilsIo.ConvertToAssetPath Failed!(Dir:{iDir})");
                    return null;
                }
            }

            // 目录校验
            if (iExistVerify && !string.IsNullOrEmpty(fullDir))
            {
                UtilsIo.CheckAndCreateDirByFullDir(fullDir);
            }
			
            return dirTmp;
        }

        /// <summary>
        /// 取得序列化文件路径
        /// </summary>
        /// <param name="iEditor">编辑器模式</param>
        /// <returns>序列化文件路径</returns>
        public static string GetAssetPath(bool iEditor = false)
        {
            return iEditor ? Const.HK_EDITOR_SASSET_DIR : Const.HK_RESOURCE_ASSETS;
        }
        
        /// <summary>
        /// 取得序列化文件路径
        /// </summary>
        /// <param name="iEditor">编辑器模式</param>
        /// <param name="iExistCheck">存在校验</param>
        /// <typeparam name="TAsset">取得序列化文件类型</typeparam>
        /// <returns>序列化文件路径</returns>
        private static string GetAssetPath<TAsset>(bool iEditor = false, bool iExistCheck = false) where TAsset : SAsset
        {
            var assetDir = GetAssetPath(iEditor);
            if (string.IsNullOrEmpty(assetDir)) return null;

            // 存在校验
            if (iExistCheck)
            {
                if (!UtilsIo.CheckAndCreateDirByFullDir(assetDir))
                {
                    HLogger.LInfo($"UtilsAsset::GetAssetPath():UtilsIo.CheckAndCreateDirByFullDir():Failed!(Dir:{assetDir})");
                    return null;
                }
            }

            return $"{assetDir}/{typeof(TAsset).Name}.asset";
        }

#region Load

        /// <summary>
        /// 通过加载文件导入
        /// </summary>
        /// <param name="iFilePath">文件路径</param>
        /// <returns>导入对象的世界内容(Json格式的字符串)</returns>
        private static string LoadTextFile(string iFilePath)
        {
            // 若已经有文件不存在
            if (!File.Exists(iFilePath))
            {
                HLogger.Warning($"UtilsAsset::ImportByLoadFile():File not exist!!!(File:{iFilePath})");
                return null;
            }

            HLogger.LInfo($"UtilsAsset::ImportByLoadFile(): <- {iFilePath}");
            return File.ReadAllText(iFilePath);
        }

        /// <summary>
        /// 加载Asset - 同步
        /// </summary>
        /// <typeparam name="TAsset">可序列化文件类型</typeparam>
        /// <returns>可序列化文件对象</returns>
        public static TAsset LoadAssetSync<TAsset>() where TAsset : SAsset
        {
            var assetPath = GetAssetPath<TAsset>(false, !Application.isMobilePlatform);
            if (UtilsIo.ConvertToResourcesPath(assetPath, out var oResPath))
            {
                if (string.IsNullOrEmpty(oResPath))
                {
                    HLogger.Error($"UtilsAsset::LoadAssetSync():The resource path of asset is null or empty!(Path:{assetPath})");
                    return default(TAsset);
                }    
            
                var dstAsset = Resources.Load<TAsset>(oResPath);
                if (default(TAsset) == dstAsset)
                {
                    HLogger.Error($"UtilsAsset::LoadAssetSync():Resources.Load() Failed!(Path:{assetPath})");
                    return default(TAsset);
                }

                return dstAsset; 
            }

            return default(TAsset);
        }

#endregion

#region Json

#region Import

        /// <summary>
        /// 导入 - Json
        /// </summary>
        /// <param name="iPath">文件路径</param>
        /// <typeparam name="TJson">Json数据类型.</typeparam>
        public static TJson ImportFromJsonByPathSync<TJson>(string iPath) where TJson : JsonData
        {
            string jsonTxt = null;
            if (!UtilsIo.IsAssetPath(iPath, out var oAssetPath))
            {
                jsonTxt = LoadTextFile(iPath);
            }
            else
            {
                // TODO:若是资源被打包进Ab，则此处需要追加从Ab读取存档文件
                
                if (UtilsIo.ConvertToResourcesPath(oAssetPath, out var oResPath))
                {
                    if (!string.IsNullOrEmpty(oResPath))
                    {
                        var textAsset = Resources.Load<TextAsset>(oResPath);
                        if (null != textAsset)
                        {
                            jsonTxt = textAsset.text;
                        }
                    }
                }
                else
                {
                    jsonTxt = LoadTextFile(iPath);
                }
            }

            return ImportFromJsonSync<TJson>(jsonTxt);

        }

        /// <summary>
        /// 导入 - Json
        /// </summary>
        /// <param name="iContext">内容</param>
        /// <typeparam name="TJson">Json数据类型.</typeparam>
        private static TJson ImportFromJsonSync<TJson>(string iContext) where TJson : JsonData
        {
            var jsonData = default(TJson);
#if UNITY_EDITOR
            try
            {
#endif
                if (string.IsNullOrEmpty(iContext)) return default(TJson);
                jsonData = UtilsJson<TJson>.ConvertFromJsonString(iContext);
#if UNITY_EDITOR
            }
            catch (Exception exp)
            {
                HLogger.Fatal("UtilsAsset::ImportByPathSync()::Failed!!! \n " +
                              $"ClassName:{typeof(TJson).Name} \n" +
                              $"Exception:{exp.Message} \n StackTrace:{exp.StackTrace}");
                jsonData = default(TJson);
            }
#endif

            return jsonData;
        }

#endregion

#region Export
        
        /// <summary>
        /// 导出 - Json
        /// </summary>
        /// <param name="iJson">Json数据格式.</param>
        /// <param name="iPath">文件路径</param>
        /// <returns>导出路径.</returns>
        /// <typeparam name="TJson">Json数据类型.</typeparam>
        public static string ExportToJsonSync<TJson>(TJson iJson, string iPath) 
            where TJson : JsonData
        {

            if (string.IsNullOrEmpty(iPath)) return null;

            var jsonPath = iPath;
            var flg = false;
#if UNITY_EDITOR
            try
            {
#endif

                var dirTmp = UtilsIo.GetFileDirByPath(jsonPath);
                if (!UtilsIo.CheckAndCreateDirByFullDir(dirTmp))
                {
                    HLogger.Error($"ExportToJsonSync():UtilsIo.CheckAndCreateDirByFullDir() Failed!(Dir:{dirTmp})");
                    return null;
                }
                
                // 获得文件Json数据
                var jsonString = UtilsJson<TJson>.ConvertToJsonString(iJson);
                
                // 写入到导出文件中
                flg = UtilsIo.WriteTxtFile(jsonPath, jsonString, true);
                if (flg)
                {
                    HLogger.LInfo ($"UtilsAsset::ExportSync(). -> Path:{jsonPath} \n  Data：{jsonString}");
                }
                
#if UNITY_EDITOR
            }
            catch (Exception exp)
            {
                HLogger.Fatal($"UtilsAsset::ExportToJsonSync()::Failed!!! \n " +
                              $"ClassName:{typeof(TJson).Name} \n AssetFile:{jsonPath ?? "null"} \n " +
                              $"Exception:{exp.Message} \n StackTrace:{exp.StackTrace}");
                jsonPath = null;
            }
#endif
            return jsonPath;
        }

#endregion
        
#endregion
        
    }
}
